﻿//NOTE: Do not exten Object.prototype http://bugs.jquery.com/ticket/2721

//compares two objects
Object.equals = function (x, y) {
    if (x === y) return true;
    if (!(x instanceof Object) || !(y instanceof Object)) return false;
    if (x.constructor !== y.constructor) return false;
    for (var p in x) {
        if (!x.hasOwnProperty(p)) continue;
        if (!y.hasOwnProperty(p)) return false;
        if (x[p] === y[p]) continue;
        if (typeof (x[p]) !== "object") return false;
        if (!Object.equals(x[p], y[p])) return false;
    }
    for (p in y) {
        if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false;
    }
    return true;
};
//comparison of 2 objects basend on stringified fields
Object.stateEquals = function (x, y) {
    for (var p in x) {
        if (!x.hasOwnProperty(p)) continue;
        if (!y.hasOwnProperty(p)) return false;
        if (x[p].toString() != y[p].toString()) return false;
    }
    for (p in y) {
        if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) return false;
    }
    return true;
}

//check if object has specyfied function. if not throws exception or simply returns false
Object.hasFunction = function (instance, name, throwException, throwMessage) {
    if (typeof instance[name] === 'function')
        return true;
    if (throwException)
        throw throwMessage || ("Function " + name + " not defined");
    return false;
};

//add days to data object in correct way
Date.prototype.addDays = function (days) {
    this.setDate(this.getDate() + days);
    return this;
};

//removes items from array by condition delegate
Array.prototype.remove = function (condition) {
    for (var i = this.length - 1; i >= 0; i--) {
        if (condition.call(this[i])) {
            this.splice(i, 1);
        }
    }
};

//gets first match element
Array.prototype.getOne = function (filter) {
    for (var i = 0; i < this.length; i++) {
        if (filter(this[i])) {
            return this[i];
        }
    }
    return null;
};

//serializes form to object
$.fn.serializeObject = function () {
    var o = {};
    var a = this.serializeArray();
    $.each(a, function () {
        if (o[this.name] !== undefined) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

////John Resig Micro-Templating
//(function () {
//    var cache = {};

//    this.tmpl = function tmpl(str, data) {
//        // Figure out if we're getting a template, or if we need to
//        // load the template - and be sure to cache the result.
//        var fn = !/\W/.test(str) ?
//      cache[str] = cache[str] ||
//        tmpl(document.getElementById(str).innerHTML) :
//        
//        // Generate a reusable function that will serve as a template
//        // generator (and which will be cached).
//      new Function("obj",
//        "var p=[],print=function(){p.push.apply(p,arguments);};" +

//        // Introduce the data as local variables using with(){}
//        "with(obj){p.push('" +

//        // Convert the template into pure JavaScript
//        str
//          .replace(/[\r\t\n]/g, " ")
//          .split("<%").join("\t")
//          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
//          .replace(/\t=(.*?)%>/g, "',$1,'")
//          .split("\t").join("');")
//          .split("%>").join("p.push('")
//          .split("\r").join("\\'")
//      + "');}return p.join('');");

//        // Provide some basic currying to the user
//        return data ? fn(data) : fn;
//    };
//})();


